
#include "shogistate.h"
#include "../common/shogicommandmap.h"
#include "shogiregistry.h"

bool ShogiState::processCommand(ShogiCommand cmd)
{
	bool bResult = true;
	LOGSERVER("processCommand");

	switch(m_gameState)
	{
	case INITIALISED:
		LOGSERVER("State: INITIALISED");
		break;
	case HANDSHAKE:
		{		
			LOGSERVER("State: HANDSHAKE");
			bResult = doHandshake(cmd);			
			if (bResult && m_handshake.checkFlag("handshake_completed"))
			{
				// Handshake is okay! Progress to next state for player one.
				LOGSERVER("HANDSHAKE completed! Switching state.");
				changeState(WAIT_FOR_PLAYER);				
			}
		}
		break;
	case WAIT_FOR_PLAYER:
		LOGSERVER("State: WAIT_FOR_PLAYER");		
		break;
	case GAME_NEGOTIATION:
		{
			LOGSERVER("State: GAME_NEGOTIATION");
			bResult = doGameNegotation(cmd);

			if (bResult && m_gamenegotiation.checkFlag("game_params_accepted"));
			{
				LOGSERVER("Player finished with gamenegotiation, waiting for other player.");
				emit signalWaitingForOtherPlayer(m_playerid);
			}
		}
		break;
	default:
		LOGSERVER("State: <error - undefined gamestate>");
		bResult = false;
		break;
	}

	return bResult;
}


bool ShogiState::doHandshake(ShogiCommand cmd)
{
	bool bResult = true;
	CommandCode cmdid;

	LOGSERVER("doHandshake");

	cmdid = findCommand(cmd);

	if (cmdid == NO_COMMAND_FOUND)
	{
		LOGSERVER("Error - NO_COMMAND_FOUND");
		m_error.setError(ERROR_PARSING_COMMAND);
		bResult = false;
	}
	else
	{
		switch(cmdid)
		{
		case CLIENT_VERSION:		  // 1.											   
			{						

				ShogiCommand sendCmd(cmd.getPlayer());				
				if (!m_handshake.checkFlag("handshake_completed"))
				{
					LOGSERVER("Handling CLIENT_VERSION command.");
					// TODO: Create real version handling here...
					m_handshake.setFlag("client_version_ok",true);
					sendCmd.setCommandAndValue(g_CommandMappings[SERVER_VERSION].cmdString,QString(SHOGI_SERVER_VERSION));
					
					LOGSERVER("Emitting signal: signalReadyToSend");
					emit signalReadyToSend(cmd.getPlayer(),sendCmd);			
					LOGSERVER("Emitted signal: signalReadyToSend");
				}
				else
				{
					LOGSERVER("Error - 1");
					
				}
			}
			break;

		case USERNAME:				  //  2.
			{
				ShogiCommand sendCmd(cmd.getPlayer());
				if (m_handshake.checkFlag("client_version_ok") && !m_handshake.checkFlag("handshake_completed"))
				{
					m_handshake.setFlag("username_ok",true);
					// TODO: Create real username handling here...
					sendCmd.setCommandAndValue(g_CommandMappings[USERNAME].cmdString,QString("OK"));
					emit signalReadyToSend(cmd.getPlayer(),sendCmd);			
				}
				else
				{
					LOGSERVER("Error - 2");

				}
			}
			break;
		case PASSWORD:				  //  3.
			{
				ShogiCommand sendCmd(cmd.getPlayer());
				if (m_handshake.checkFlag("client_version_ok") && 
					m_handshake.checkFlag("username_ok") &&
					!m_handshake.checkFlag("handshake_completed"))
				{
					m_handshake.setFlag("password_validated",true);
					m_handshake.setFlag("handshake_completed",true);
					// TODO: Create real username handling here...
					sendCmd.setCommandAndValue(g_CommandMappings[PASSWORD].cmdString,QString("OK"));
					emit signalReadyToSend(cmd.getPlayer(),sendCmd);			
				}
				else
				{
					LOGSERVER("Error - 3");
				}
			}	
			break;

		default:
			// problem
			LOGSERVER("Error - Command mapping probably does not match enumeration!");
			bResult = false;			
			break;
		}
	}

	bResult = true;

	return bResult;
}

bool ShogiState::doGameNegotation(ShogiCommand cmd)
{
	bool bResult = true;
	CommandCode cmdid;

	LOGSERVER("doGameNegotation");
	
	cmdid = findCommand(cmd);

	if (cmdid == NO_COMMAND_FOUND)
	{
		LOGSERVER("Error - NO_COMMAND_FOUND");
		m_error.setError(ERROR_PARSING_COMMAND);
		bResult = false;
	}
	else
	{
		switch(cmdid)
		{
		case GAME_PARAM:		 
			{						
				// if value is OK then parameters are accepted and we can proceed, otherwise new parameters are specified
				// and should be transfered to the other player				
				
				if (cmd.getValue().compare("OK")==0)
				{
					
					m_gamenegotiation.setFlag("game_params_accepted",true);
					ShogiCommand sendCmd(getOtherPlayer(cmd.getPlayer()));
					sendCmd.setCommandAndValue(g_CommandMappings[GAME_PARAM].cmdString,cmd.getValue());				
					LOGSERVER("Emitting signal: signalReadyToSend");
					emit signalReadyToSend(sendCmd.getPlayer(),sendCmd);			
					LOGSERVER("Emitted signal: signalReadyToSend");
					LOGSERVER("Game parameters accepted. Ready to proceed.");
					
				}
				else
				{
					ShogiCommand sendCmd(getOtherPlayer(cmd.getPlayer()));
					sendCmd.setCommandAndValue(g_CommandMappings[GAME_PARAM].cmdString,cmd.getValue());
					LOGSERVER("Emitting signal: signalReadyToSend");
					emit signalReadyToSend(sendCmd.getPlayer(),sendCmd);			
					LOGSERVER("Emitted signal: signalReadyToSend");
				}		
			}
			break;

		default:
			// problem
			LOGSERVER("Error - Command mapping probably does not match enumeration!");
			bResult = false;			
			break;
		}
	}

	bResult = true;
	
	return bResult;
}

CommandCode ShogiState::findCommand(ShogiCommand cmd)
{
	CommandCode cmdid = NO_COMMAND_FOUND;
	bool bResult  = false;
	LOGSERVER("findCommand");
	LOGSERVER(QString("Looking for ") + cmd.getCommand()); 

	for (int i = 0; i < COMMANDCODES_COUNT; i++)
	{
		if ((g_CommandMappings[i].gameState == m_gameState || ALL_STATES ))
		{
			if (cmd.getCommand().compare(g_CommandMappings[i].cmdString) == 0)
			{
				LOGSERVER("Found command.");
				cmdid = g_CommandMappings[i].cmdCode;
				bResult = true;
				break;
			}
		}
				
	}

	return cmdid;
}




void ShogiState::changeState(GameState state) 
{ 
	m_gameState = state;

	emit signalStateChange(m_playerid);
}	